package com.open.jacekkowalczyk.xmlrpc.bugzilla;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.httpclient.HttpClient;
import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.client.XmlRpcCommonsTransportFactory;

import com.open.jacekkowalczyk.Xml2Map;

/**
 * Hello world!
 */
public class BugzillaIssuesCreator {

    private static Logger LOGGER = Logger.getLogger(BugzillaIssuesCreator.class);

    public static void main(final String args[]) throws MalformedURLException, XmlRpcException {

        final Properties applicationConfig = new Properties();
        try {
            applicationConfig.load(BugzillaIssuesCreator.class.getClassLoader().getResourceAsStream("config.properties"));
        } catch (final IOException e) {
            e.printStackTrace();
            System.exit(1);
        }

        String inputFilePath = "issues.xml";
        String userName = "";
        String password = "";

        final Options options = new Options();
        options.addOption("i", "input-file", true, "xml input file, REQUIRED");
        options.addOption("u", "user", true, "bugzilla user name, REQUIRED");
        options.addOption("p", "password", true, "bugzilla password, REQUIRED");
        options.addOption("v", "verbose", false, "Enable verbose output, OPTIONAL, default is disabled");

        final org.apache.commons.cli.CommandLineParser parser = new PosixParser();
        try {
            final CommandLine cmd = parser.parse(options, args);

            final boolean verboseOn = cmd.hasOption("v");
            final boolean userON = cmd.hasOption("u");
            final boolean passON = cmd.hasOption("p");
            final boolean inputON = cmd.hasOption("i");
            if (userON && passON & inputON) {

                inputFilePath = cmd.getOptionValue("i");
                userName = cmd.getOptionValue("u");
                password = cmd.getOptionValue("p");

                final HttpClient httpClient = new HttpClient();
                final XmlRpcClient rpcClient = new XmlRpcClient();
                final XmlRpcCommonsTransportFactory factory = new XmlRpcCommonsTransportFactory(rpcClient);
                final XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();

                factory.setHttpClient(httpClient);
                rpcClient.setTransportFactory(factory);
                config.setServerURL(new URL(applicationConfig.getProperty("url")));
                rpcClient.setConfig(config);

                // map of the login data
                final Map<String, String> loginMap = new HashMap<String, String>();

                loginMap.put("login", userName);

                loginMap.put("password", password);
                loginMap.put("rememberlogin", applicationConfig.getProperty("rememberlogin"));

                // login to bugzilla
                final Object loginResult = rpcClient.execute("User.login", new Object[] {loginMap});
                printOutput("loginResult=" + loginResult, verboseOn);

                // Read Issues From Input File
                final Xml2Map xml2Mapreader = new Xml2Map();

                final File file = new File(inputFilePath);
                final List<Map<String, String>> issues = xml2Mapreader.getListOfLevel1MapElelements(file, "issues", "issue");

                // For Each Issue Execute
                // map of the bug data
                for (final Map<String, String> issueMap : issues) {
                    final Object createResult = createIssue(rpcClient, issueMap);
                    printOutput("createResult = " + createResult, verboseOn);
                }

                // end for each

            } else {
                printUsage(options);
            }

        } catch (final ParseException e) {
            e.printStackTrace();
        }

    }

    /**
     * @param rpcClient
     * @param issueParamsMap
     * @return
     * @throws XmlRpcException
     */
    private static Object createIssue(final XmlRpcClient rpcClient, final Map<String, String> issueParamsMap)
        throws XmlRpcException {

        // create bug
        final Object createResult = rpcClient.execute("Bug.create", new Object[] {issueParamsMap});
        return createResult;
    }

    public static void printUsage(final Options options) {
        final HelpFormatter formatter = new HelpFormatter();
        final StringBuilder usageSb = new StringBuilder();
        usageSb
            .append("java -jar bugzilla-java-xmlrpc-jar-with-dependencies.jar [-v] -i <input file> -u <user> -p <password>");
        final StringBuilder header = new StringBuilder();
        header.append("\nbugzilla-java-xmlrpc\n");
        header.append("Description of the application:\n");
        header.append("Application add issues to bugzilla frok input file using xml rpc");
        formatter.printHelp(usageSb.toString(), header.toString(), options,
            "\nFor more information please check webpage http://my.application.com.example");
    }

    private static void printOutput(final String message, final boolean verbose) {
        if (verbose) {
            LOGGER.debug(message);
        }
    }

}
